package tester;

import java.lang.reflect.Field;
import java.util.TreeMap;

import org.apache.log4j.Logger;

/**
 * Modify is a class with one static method, modify, that takes in an
 * indeterminate number of EffectFields and affects the changes on the generic
 * object t which was passed as an argument as well.
 * 
 * @author w_jossey
 * 
 */
public class Modify {
	private static final Logger logger = Logger.getLogger(Modify.class);

	public static <T> T modify(T t, EffectField... effectFields)
			throws Exception {
		for (EffectField e : effectFields) {
			String fieldName = e.getName();
			try {
				
				Field f = getDeclaredFieldAll(t, fieldName);
				if(f != null){
					f.set(t, e.getValue());
					//ReflectionHelper.setStaticFinalField(t, f, e.getValue());
				}else{
					throw new Exception("Field was not found in the object" +
							"hierarchy.");
				}
			} catch (SecurityException e1) {
				logger.error(e1.getLocalizedMessage());
			}
		}

		return t;
	}
	
	private static <T> TreeMap<String, Field> getAllFieldsWithSuper(T t){
		Class<?> clazz = t.getClass();

		//Create our TreeSet
		TreeMap<String, Field> fields = new TreeMap<String, Field>();
		
		while(clazz != null){
			Field[] tempFields = clazz.getDeclaredFields();
			for(Field tempField : tempFields){
				tempField.setAccessible(true);
				fields.put(tempField.getName(), tempField);
			}
			
			clazz = clazz.getSuperclass();
		}
		
		return fields;
	}
	
	/* 
	 * Helper method.  Returns the field from the object with the given name.
	 * Returns null if it is not found.
	 */
	private static <T> Field getDeclaredFieldAll(T t, String fieldName){
		TreeMap<String, Field> fields = getAllFieldsWithSuper(t);
		return fields.get(fieldName);
	}
	
}
